import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
import 'package:get/get.dart';

import '../models/file_metadata.dart';
import '../models/virtual_file_node.dart';
import '../models/tianyi_user.dart';
import '../models/upload_task.dart';
import '../models/download_task.dart';

class DatabaseService extends GetxService {
  static const String _databaseName = 'snail_netdisk.db';
  static const int _databaseVersion = 1;

  Database? _database;

  Database get database {
    if (_database == null) {
      throw Exception('Database not initialized. Call init() first.');
    }
    return _database!;
  }

  @override
  Future<void> onInit() async {
    super.onInit();
    await init();
  }

  Future<void> init() async {
    final databasePath = await getDatabasesPath();
    final path = join(databasePath, _databaseName);

    _database = await openDatabase(
      path,
      version: _databaseVersion,
      onCreate: _onCreate,
      onUpgrade: _onUpgrade,
    );
  }

  Future<void> _onCreate(Database db, int version) async {
    // 文件元数据表
    await db.execute('''
      CREATE TABLE file_metadata (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        md5 TEXT NOT NULL UNIQUE,
        file_name TEXT NOT NULL,
        file_size INTEGER NOT NULL,
        mime_type TEXT,
        cloud_id TEXT,
        created_time TEXT NOT NULL,
        updated_time TEXT NOT NULL
      )
    ''');

    // 虚拟文件系统表
    await db.execute('''
      CREATE TABLE virtual_file_nodes (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        type TEXT NOT NULL,
        parent_id INTEGER,
        file_md5 TEXT,
        path TEXT NOT NULL UNIQUE,
        created_time TEXT NOT NULL,
        updated_time TEXT NOT NULL,
        is_deleted INTEGER DEFAULT 0,
        FOREIGN KEY (file_md5) REFERENCES file_metadata (md5),
        FOREIGN KEY (parent_id) REFERENCES virtual_file_nodes (id)
      )
    ''');

    // 天翼云用户表
    await db.execute('''
      CREATE TABLE tianyi_users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        user_id TEXT UNIQUE,
        nickname TEXT,
        avatar TEXT,
        phone TEXT,
        email TEXT,
        total_space INTEGER,
        used_space INTEGER,
        session_key TEXT,
        session_secret TEXT,
        login_time TEXT,
        expire_time TEXT,
        is_logged_in INTEGER DEFAULT 0
      )
    ''');

    // 上传任务表
    await db.execute('''
      CREATE TABLE upload_tasks (
        id TEXT PRIMARY KEY,
        file_name TEXT NOT NULL,
        file_path TEXT NOT NULL,
        file_size INTEGER NOT NULL,
        md5 TEXT NOT NULL,
        mime_type TEXT,
        target_path TEXT NOT NULL,
        status TEXT NOT NULL,
        uploaded_bytes INTEGER DEFAULT 0,
        progress REAL DEFAULT 0.0,
        error_message TEXT,
        created_time TEXT NOT NULL,
        start_time TEXT,
        completed_time TEXT,
        cloud_id TEXT,
        upload_url TEXT,
        upload_params TEXT
      )
    ''');

    // 下载任务表
    await db.execute('''
      CREATE TABLE download_tasks (
        id TEXT PRIMARY KEY,
        file_name TEXT NOT NULL,
        cloud_id TEXT NOT NULL,
        download_url TEXT NOT NULL,
        save_path TEXT NOT NULL,
        file_size INTEGER NOT NULL,
        md5 TEXT NOT NULL,
        status TEXT NOT NULL,
        downloaded_bytes INTEGER DEFAULT 0,
        progress REAL DEFAULT 0.0,
        error_message TEXT,
        created_time TEXT NOT NULL,
        start_time TEXT,
        completed_time TEXT
      )
    ''');

    // 创建索引
    await db.execute('CREATE INDEX idx_file_metadata_md5 ON file_metadata (md5)');
    await db.execute('CREATE INDEX idx_virtual_file_nodes_path ON virtual_file_nodes (path)');
    await db.execute('CREATE INDEX idx_virtual_file_nodes_parent_id ON virtual_file_nodes (parent_id)');
    await db.execute('CREATE INDEX idx_upload_tasks_status ON upload_tasks (status)');
    await db.execute('CREATE INDEX idx_download_tasks_status ON download_tasks (status)');

    // 插入根目录
    await db.insert('virtual_file_nodes', {
      'name': 'root',
      'type': 'folder',
      'parent_id': null,
      'file_md5': null,
      'path': '/',
      'created_time': DateTime.now().toIso8601String(),
      'updated_time': DateTime.now().toIso8601String(),
      'is_deleted': 0,
    });
  }

  Future<void> _onUpgrade(Database db, int oldVersion, int newVersion) async {
    // 数据库升级逻辑
  }

  // 文件元数据操作
  Future<int> insertFileMetadata(FileMetadata metadata) async {
    return await database.insert('file_metadata', metadata.toMap(),
        conflictAlgorithm: ConflictAlgorithm.replace);
  }

  Future<FileMetadata?> getFileMetadataByMd5(String md5) async {
    final List<Map<String, dynamic>> maps = await database.query(
      'file_metadata',
      where: 'md5 = ?',
      whereArgs: [md5],
    );
    if (maps.isNotEmpty) {
      return FileMetadata.fromMap(maps.first);
    }
    return null;
  }

  Future<List<FileMetadata>> getAllFileMetadata() async {
    final List<Map<String, dynamic>> maps = await database.query('file_metadata');
    return maps.map((map) => FileMetadata.fromMap(map)).toList();
  }

  Future<void> deleteFileMetadata(String md5) async {
    await database.delete('file_metadata', where: 'md5 = ?', whereArgs: [md5]);
  }

  // 虚拟文件系统操作
  Future<int> insertVirtualFileNode(VirtualFileNode node) async {
    return await database.insert('virtual_file_nodes', node.toMap());
  }

  Future<VirtualFileNode?> getVirtualFileNodeByPath(String path) async {
    final List<Map<String, dynamic>> maps = await database.query(
      'virtual_file_nodes',
      where: 'path = ? AND is_deleted = 0',
      whereArgs: [path],
    );
    if (maps.isNotEmpty) {
      return VirtualFileNode.fromMap(maps.first);
    }
    return null;
  }

  Future<List<VirtualFileNode>> getChildrenByParentId(int? parentId) async {
    final List<Map<String, dynamic>> maps = await database.query(
      'virtual_file_nodes',
      where: 'parent_id = ? AND is_deleted = 0',
      whereArgs: [parentId],
      orderBy: 'type DESC, name ASC', // 文件夹在前，按名称排序
    );
    return maps.map((map) => VirtualFileNode.fromMap(map)).toList();
  }

  Future<void> updateVirtualFileNode(VirtualFileNode node) async {
    await database.update(
      'virtual_file_nodes',
      node.toMap(),
      where: 'id = ?',
      whereArgs: [node.id],
    );
  }

  Future<void> deleteVirtualFileNode(int id) async {
    await database.update(
      'virtual_file_nodes',
      {'is_deleted': 1, 'updated_time': DateTime.now().toIso8601String()},
      where: 'id = ?',
      whereArgs: [id],
    );
  }

  Future<List<VirtualFileNode>> getDeletedNodes() async {
    final List<Map<String, dynamic>> maps = await database.query(
      'virtual_file_nodes',
      where: 'is_deleted = 1',
      orderBy: 'updated_time DESC',
    );
    return maps.map((map) => VirtualFileNode.fromMap(map)).toList();
  }

  Future<void> restoreVirtualFileNode(int id) async {
    await database.update(
      'virtual_file_nodes',
      {'is_deleted': 0, 'updated_time': DateTime.now().toIso8601String()},
      where: 'id = ?',
      whereArgs: [id],
    );
  }

  Future<void> permanentlyDeleteVirtualFileNode(int id) async {
    await database.delete('virtual_file_nodes', where: 'id = ?', whereArgs: [id]);
  }

  // 天翼云用户操作
  Future<int> insertOrUpdateTianyiUser(TianyiUser user) async {
    return await database.insert('tianyi_users', user.toMap(),
        conflictAlgorithm: ConflictAlgorithm.replace);
  }

  Future<TianyiUser?> getCurrentTianyiUser() async {
    final List<Map<String, dynamic>> maps = await database.query(
      'tianyi_users',
      where: 'is_logged_in = 1',
      limit: 1,
    );
    if (maps.isNotEmpty) {
      return TianyiUser.fromMap(maps.first);
    }
    return null;
  }

  Future<void> logoutTianyiUser() async {
    await database.update(
      'tianyi_users',
      {'is_logged_in': 0},
      where: 'is_logged_in = 1',
    );
  }

  // 上传任务操作
  Future<void> insertUploadTask(UploadTask task) async {
    await database.insert('upload_tasks', task.toMap(),
        conflictAlgorithm: ConflictAlgorithm.replace);
  }

  Future<void> updateUploadTask(UploadTask task) async {
    await database.update(
      'upload_tasks',
      task.toMap(),
      where: 'id = ?',
      whereArgs: [task.id],
    );
  }

  Future<List<UploadTask>> getAllUploadTasks() async {
    final List<Map<String, dynamic>> maps = await database.query(
      'upload_tasks',
      orderBy: 'created_time DESC',
    );
    return maps.map((map) => UploadTask.fromMap(map)).toList();
  }

  Future<void> deleteUploadTask(String id) async {
    await database.delete('upload_tasks', where: 'id = ?', whereArgs: [id]);
  }

  // 下载任务操作
  Future<void> insertDownloadTask(DownloadTask task) async {
    await database.insert('download_tasks', task.toMap(),
        conflictAlgorithm: ConflictAlgorithm.replace);
  }

  Future<void> updateDownloadTask(DownloadTask task) async {
    await database.update(
      'download_tasks',
      task.toMap(),
      where: 'id = ?',
      whereArgs: [task.id],
    );
  }

  Future<List<DownloadTask>> getAllDownloadTasks() async {
    final List<Map<String, dynamic>> maps = await database.query(
      'download_tasks',
      orderBy: 'created_time DESC',
    );
    return maps.map((map) => DownloadTask.fromMap(map)).toList();
  }

  Future<void> deleteDownloadTask(String id) async {
    await database.delete('download_tasks', where: 'id = ?', whereArgs: [id]);
  }

  Future<void> close() async {
    await _database?.close();
    _database = null;
  }
}